using System;
using System.Collections.Generic;
using System.Text;
using Watchdog.Bll;
using Watchdog.Bll.Factory;
using log4net;

namespace Watchdog.Engines {
    public class ScheduleEngine {

        #region [ Private variables ]
        Dictionary<int, Schedule> RunningSchedules = new Dictionary<int, Schedule> ();
        Dictionary<Schedule, Test> RunningTests = new Dictionary<Schedule, Test> ();

        List<TestUnit> intranettestunits = new List<TestUnit> ();
        List<TestUnit> dmztestunits = new List<TestUnit> ();
        List<TestUnit> internettestunits = new List<TestUnit> ();

        public List<TestUnit> IntranetTestUnits {
            get { return intranettestunits; }
            set { intranettestunits = value; }
        }
        public List<TestUnit> DmzTestUnits {
            get { return dmztestunits; }
            set { dmztestunits = value; }
        }
        public List<TestUnit> InternetTestUnits {
            get { return internettestunits; }
            set { internettestunits = value; }
        }
        MinuteTimer scheduletimer = new MinuteTimer ();
        ILog log;
        #endregion

        public ScheduleEngine () {
            log = log4net.LogManager.GetLogger ("servicehost.Logging");
            scheduletimer.Elapsed += new System.Timers.ElapsedEventHandler ( scheduletimer_Elapsed );
        }

        public ScheduleEngineStatus Status {
            get { return status; }
            internal set { status = value; }
        }ScheduleEngineStatus status = ScheduleEngineStatus.Stopped;

        public void Start () {
            // Retrieve the TestUnits;
            //IntranetTestUnits = TestUnitFactory.GetByZone ("Intranet");
            //Log.Write (Severity.Info, "Loaded " + IntranetTestUnits.Count.ToString () + " TestUnits for zone 'Intranet'.");
            //DmzTestUnits = TestUnitFactory.GetByZone ("Dmz");
            //Log.Write (Severity.Info, "Loaded " + DmzTestUnits.Count.ToString () + " TestUnits for zone 'Dmz'.");
            //InternetTestUnits = TestUnitFactory.GetByZone ("Internet");
            //Log.Write (Severity.Info, "Loaded " + InternetTestUnits.Count.ToString () + " TestUnits for zone 'Internet'.");
            // Start the timer.
            scheduletimer.Start ();
            Status = ScheduleEngineStatus.Running;
        }
        public void Stop () {
            // Stop the timer
            scheduletimer.Stop ();
            Status = ScheduleEngineStatus.Stopped;
        }

        void scheduletimer_Elapsed ( object sender, System.Timers.ElapsedEventArgs e ) {
            // retrieve the schedules
            //Log.Write(Severity.Info,"Retrieving Schedules");
            try {
                List<Schedule> result = ScheduleFactory.GetPending ();
                Log.Write(Severity.Info,result.Count.ToString () + " Schedules retrieved.");
                // lock the schedules in the db
                foreach (Schedule sched in result) {
                    sched.Lock ();
                    RunningSchedules.Add ( sched.Id, sched );
                    RunningTests.Add (sched, sched.Test);
                    DispatchSchedule (sched);
                }
                //Log.Write(Severity.Info, "End retrieving Schedules");
            } catch (System.Exception ex) {
                Log.Write(Severity.Fatal,this, ex);
            }
        }

        void DispatchSchedule ( Schedule schedule ) {
            Log.Write (Severity.Info, "Dispatched Test : " + schedule.Test.Name);
            Log.Write (Severity.Info, "Dispatched Test : " + schedule.Test.Zone);
            
        }

        TestUnit FindLeastUsedTestUnit ( List<TestUnit> units ) {
            lock (units) {
                TestUnit outresult = null;
                foreach (TestUnit unit in units) {
                    if (outresult == null)
                        outresult = unit;
                    if (unit.AssignedTests.Count < outresult.AssignedTests.Count)
                        outresult = unit;
                }
                return outresult;
            }
        }
    }

    public enum ScheduleEngineStatus {
        Stopped = 0,
        Running = 1
    }
}
